package core;

import java.io.FileReader;
import java.io.IOException;
import java.util.Comparator;
import java.util.Set;


/**
 * @author tptak
 * Abstract class for problems description
 */
public abstract class Problem {
	/**
	 * comparator for results
	 */
	protected Comparator<Result> comparator = new Comparator<Result>() {

		
		public int compare(Result o1, Result o2) {
			double d = (o2.result)[0]-(o1.result)[0];
			if(d>0) return -1;
			if(d<0) return 1;
			return 0;
		}
		
	};
	/**
	 * Name of a problem described
	 */
	protected String name;

	/**
	 * Lower Bounds of decision variables indexed from 1 to the length of the array
	 */
	protected double firstLowerBounds[];
	/**
	 * Upper Bounds of decision variables indexed from 1 to the length of the array
	 */
	protected double firstUpperBounds[];
	/**
	 * Lower Bounds of decision variables indexed from the first after length of the array to the end
	 */
	protected double restLowerBounds;
	/**
	 * Upper Bounds of decision variables indexed from the first after length of the array to the end
	 */
	protected double restUpperBounds;
	
	/**
	 * Array of values to determine aim of optimization - true for maximization and false for minimization
	 */
	protected ObjectiveTarget objectiveTargets[];
	
	/**
	 * Calculates the objective functions values based on given decision variables
	 * @param genotype Array of decision variables for a given instance of solution
	 * @return Array of values of objective functions in a problem
	 */
	public abstract double[] calculate(double genotype[]);
	
	/**
	 * Loads data from a file and saves it in Problem object.
	 * @param fr FileReader with data to load
	 * @throws IOException
	 */
	public void loadData(FileReader fr) throws IOException {}
	
	/**
	 * Returns a string with optimal solution in gnuplot plottable format
	 * @return String with an optimal solution function or null if it doesn't exist
	 */
	public String getOptimalSolution() {
		return null;
	}
	
	public double getHVR(Set<Result> results) {
		return 1.0;
	}
	
	public boolean isFirstDominatingTheOther(double[] result1, double[] result2) throws IndexOutOfBoundsException {
		if( (result1.length != result2.length) && (result1.length != this.objectiveTargets.length)) {
			throw new IndexOutOfBoundsException("Arrays lenghts not equal.");
		}
		
		boolean result = false;
		
		try {
			int i=0;
			while(true) {
				if((objectiveTargets[i]==ObjectiveTarget.MAXIMIZE && (result1[i]>result2[i])) || (objectiveTargets[i]==ObjectiveTarget.MINIMIZE && (result1[i]<result2[i]))) {
					result = true;
				} else if ((objectiveTargets[i]==ObjectiveTarget.MAXIMIZE && (result1[i]<result2[i])) || (objectiveTargets[i]==ObjectiveTarget.MINIMIZE && (result1[i]>result2[i]))) {
					return false;
				}
				i++;
			}
		} catch (ArrayIndexOutOfBoundsException e) {
			//tu nic nie robimy!
		}
		
		return result;
	}
	
	public double[] normalize(double[] genotype) {
		int i = 0;
		double sum = 0.0;
		try{
			while(true) {
				sum += genotype[i++];
			}
		}catch(Exception e) {}
		i = 0;
		try{
			while(true) {
				genotype[i++]/=sum;
			}
		}catch(Exception e) {}
		return genotype;
	}
	
	public double getUpperBound(int genotypeIndex) {
		if(firstUpperBounds.length<genotypeIndex+1)
			return this.restUpperBounds;
		return this.firstUpperBounds[genotypeIndex];
	}
	
	public double getLowerBound(int genotypeIndex) {
		if(firstLowerBounds.length<genotypeIndex+1)
			return this.restLowerBounds;
		return this.firstLowerBounds[genotypeIndex];
	}
	
	public String toString() {
		return this.name;
	}
	
	/**
	 * Metoda wykonuje analiz� otrzymanych wynik�w. zwraca informacje,
	 *  jakie s� mo�liwe sk�ady portfeli inwestycyjnych,
	 *  ile got�wki niewykorzystanej (przyci�cia),
	 *  ile spodziewanego zwrotu, jaki procent. 
	 *  analiza wykonywana dla okre�lonej ilo�ci przyk�ad�w 
	 *  (parametr programu, domy�lnie 10)
	 * @param properties - w�asno�� analizy - kapita� inwestycji
	 * @return opis wynik�w analizy
	 */
	public String performAnalysis(Double capital, Integer analysisNumber, Set<Result> tt) {
	
		
		return null;
	}
}
